package mytask.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.validation.Valid;

import mytask.dao.ProjectDAO;
import mytask.dao.TicketDAO;
import mytask.domain.AuthManager;
import mytask.domain.TranslationManager;
import mytask.model.Project;
import mytask.model.ProjectMember;
import mytask.model.Ticket;
import mytask.model.TicketStatus;
import mytask.model.User;
import mytask.view.Screen;
import mytask.view.ScreenManager;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

@Controller
public final class TicketController extends MultiActionController {

	@Resource
	private ProjectDAO projectDAO;

	@Resource
	private TicketDAO ticketDAO;

	public void setProjectDAO(ProjectDAO projectDAO) {
		this.projectDAO = projectDAO;
	}

	public void setTicketDAO(TicketDAO ticketDAO) {
		this.ticketDAO = ticketDAO;
	}

	@RequestMapping(value = "/tickets/new", method = RequestMethod.GET)
	public ModelAndView newTicket(@RequestParam(value = "project-id") Integer projectId) {
		if (!AuthManager.isUserLoggedIn()) {
			return new ModelAndView(ScreenManager.REDIRECT_HOME);
		}

		return getNewTicketScreen(projectId);
	}

	@RequestMapping(value = "/tickets/view", method = RequestMethod.GET)
	public ModelAndView showTicket(@RequestParam(value = "id") int id) {
		if (!AuthManager.isUserLoggedIn()) {
			return new ModelAndView(ScreenManager.REDIRECT_HOME);
		}

		final Ticket ticket = ticketDAO.getTicket(id);
		if (ticket != null) {

			// Use following code for testing purposes only!
			/*
			 * { final String chars =
			 * "abcdefghihj klmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUVWXZ1234567689"
			 * ; final int numTickets = 500; for (int i = 0; i < numTickets;
			 * i++) { final Ticket t = new Ticket();
			 * t.setProject(ticket.getProject());
			 * t.setAssignee(ticket.getAssignee());
			 * t.setCreator(ticket.getCreator());
			 * t.setStatus(TicketStatus.values()[(int) (Math.random() * 4)]);
			 * 
			 * String title = ""; int length = 10 + (int) (Math.random() * 50);
			 * for (int j = 0; j < length; j++) { title += chars.charAt((int)
			 * (Math.random() * (chars.length() - 1))); } t.setTitle(title);
			 * 
			 * final String description = "Lorem ipsum dolor sit amet, " +
			 * "consectetur adipisicing elit, sed do eiusmod tempor incididunt ut "
			 * + "labore et dolore magna aliqua. Ut enim ad minim veniam, " +
			 * "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
			 * + "commodo consequat. Duis aute irure dolor in reprehenderit in "
			 * + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. "
			 * +
			 * "Excepteur sint occaecat cupidatat non proident, sunt in culpa "
			 * + "qui officia deserunt mollit anim id est laborum.";
			 * t.setDescription(description);
			 * 
			 * ticketDAO.saveTicket(t); } }
			 */

			final Map<String, Object> params = new HashMap<String, Object>();
			params.put("project-id", ticket.getProject().getId());
			params.put("project-title", ticket.getProject().getTitle());
			params.put("ticket-id", ticket.getId());
			params.put("ticket-title", ticket.getTitle());

			final ModelAndView screen = ScreenManager.get(Screen.TICKET_VIEW, params);
			screen.addObject("additionalStyles", new String[] { "Ticket.css" });

			final String title = "#" + ticket.getId() + ": " + ticket.getTitle();
			screen.addObject(ScreenManager.SCREEN_TITLE, title);
			screen.addObject("ticket", ticket);

			screen.addObject("ticketStatusString", ticket.getStatus().toString());

			return screen;
		}

		return ScreenManager.getErrorMessage(TranslationManager.get("message.ticket-not-found"));
	}

	@RequestMapping(value = "/tickets/edit", method = RequestMethod.GET)
	public ModelAndView editTicket(@RequestParam(value = "id") int id) {
		if (!AuthManager.isUserLoggedIn()) {
			return new ModelAndView(ScreenManager.REDIRECT_HOME);
		}

		final Ticket ticket = ticketDAO.getTicket(id);
		if (ticket != null) {
			final Map<String, Object> params = new HashMap<String, Object>();
			params.put("project-id", ticket.getProject().getId());
			params.put("project-title", ticket.getProject().getTitle());
			params.put("ticket-id", ticket.getId());
			params.put("ticket-title", ticket.getTitle());

			final ModelAndView screen = ScreenManager.get(Screen.TICKET_EDIT, params);
			screen.addObject("additionalStyles", new String[] { "Ticket.css" });

			final String title = "#" + ticket.getId() + ": " + ticket.getTitle();
			screen.addObject(ScreenManager.SCREEN_TITLE, title);

			final List<User> users = getUsersFromProjectMembers(ticket.getProject());
			screen.addObject("userList", users);
			screen.addObject("statusList", TicketStatus.values());

			screen.addObject("ticket", ticket);

			return screen;
		}

		return ScreenManager.getErrorMessage(TranslationManager.get("message.ticket-not-found"));
	}

	@RequestMapping(value = "/tickets/edit", method = RequestMethod.POST)
	public ModelAndView saveTicket(@RequestParam("assignee_id") int assigneeId,
			@Valid @ModelAttribute("ticket") Ticket ticket, BindingResult results) {
		if (!AuthManager.isUserLoggedIn()) {
			return new ModelAndView(ScreenManager.REDIRECT_HOME);
		}

		if (results.hasErrors()) {
			return getNewTicketScreen(ticket.getProject().getId());
		}

		ticketDAO.saveTicket(ticket);
		ticket = ticketDAO.getTicket(ticket.getId());

		setAssignee(ticket, assigneeId);
		ticketDAO.saveTicket(ticket);

		return new ModelAndView("redirect:/tickets/view?id=" + ticket.getId());
	}

	private ModelAndView getNewTicketScreen(Integer projectId) {
		final Project project = projectDAO.getProject(projectId);
		if (project == null) {
			return ScreenManager.getErrorMessage(TranslationManager.get("message.project-not-found"));
		}

		final Map<String, Object> params = new HashMap<String, Object>();
		params.put("project-id", project.getId());
		params.put("project-title", project.getTitle());
		params.put("ticket-id", 0);
		params.put("ticket-title", TranslationManager.get("title.ticket-add"));

		final ModelAndView screen = ScreenManager.get(Screen.TICKET_ADD, params);
		screen.addObject("additionalStyles", new String[] { "Ticket.css" });

		screen.addObject(ScreenManager.SCREEN_TITLE, TranslationManager.get("title.ticket-add"));

		final List<User> users = getUsersFromProjectMembers(project);
		screen.addObject("userList", users);
		screen.addObject("statusList", TicketStatus.values());

		final Ticket ticket = new Ticket();
		ticket.setProject(project);
		ticket.setAssignee(AuthManager.getPageUser());
		ticket.setCreator(AuthManager.getPageUser());

		screen.addObject("ticket", ticket);

		return screen;
	}

	private void setAssignee(final Ticket ticket, final int assigneeId) {
		final List<ProjectMember> members = ticket.getProject().getMembers();
		for (ProjectMember member : members) {
			if (member.getUser().getId() == assigneeId) {
				ticket.setAssignee(member.getUser());
				return;
			}
		}
	}

	private List<User> getUsersFromProjectMembers(final Project project) {
		final List<ProjectMember> members = project.getMembers();
		final List<User> users = new ArrayList<User>();
		for (ProjectMember member : members) {
			users.add(member.getUser());
		}
		return users;
	}

}
